package com.aos.iot.protocol.hll.parser.data;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.aos.iot.protocol.hll.util.CodeUtil;
import com.aos.iot.protocol.hll.constant.HllCmd;
import com.aos.iot.protocol.hll.constant.HllProp;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Component("RequestBindPipeDataParser")
public class InteractiveBindPipeDataParser extends HllDataParser {

    private final List<String> encodeItems = CollUtil.newArrayList(
            HllProp.PILE_NO.getValue(),
            HllProp.PILE_STATUS.getValue(),
            HllProp.PILE_CHANNEL_NO.getValue(),
            HllProp.PILE_OUTPUT_COIL_BIND_TABLE.getValue(),
            HllProp.PILE_SOFT_VERSION.getValue()
    );

    private final List<String> decodeItems = CollUtil.newArrayList(
            HllProp.PILE_NO.getValue(),
            HllProp.PILE_CHANNEL_NO.getValue(),
            HllProp.PILE_OUTPUT_COIL_BIND_TABLE.getValue()
    );

    @Override
    public Dict encode(String payload) {
        Dict data = Dict.create()
            .set(HllProp.PILE_NO.getValue(), sub(payload, 0, 10, true, "0000000000"))
            .set(HllProp.PILE_STATUS.getValue(), sub(payload, 10, 12, false, "99"));
        if(StrUtil.length(payload) > 14) {
            data.set(HllProp.PILE_CHANNEL_NO.getValue(), sub(payload, 12, 14, false, "00"));
            data.set(HllProp.PILE_OUTPUT_COIL_BIND_TABLE.getValue(),
                    bindTableParser(sub(payload, 14, 206, false, defaultBindTable(16))));
            data.set(HllProp.PILE_SOFT_VERSION.getValue(), sub(payload, 206, 208, false, "00"));
        } else {
            data.set(HllProp.PILE_SOFT_VERSION.getValue(), sub(payload, 12, 14, false, "00"));
        }
        return data;
    }

    @Override
    public List<String> encodeItems() {
        return encodeItems;
    }

    @Override
    public String decode(Dict data) {
        StringBuilder bindTable = new StringBuilder();
        Map<String, String> outputCoilBindTable = data.getBean(HllProp.PILE_OUTPUT_COIL_BIND_TABLE.getValue());
        outputCoilBindTable.forEach((k, v) -> bindTable.append(k).append(CodeUtil.highRotation(v)));
        return StrUtil.join("",
            CodeUtil.highRotation(data.getStr(HllProp.PILE_NO.getValue())),
            data.getStr(HllProp.PILE_CHANNEL_NO.getValue()),
            bindTable.toString()
        );
    }

    @Override
    public List<String> decodeItems() {
        return decodeItems;
    }

    @Override
    public String cmd() {
        return HllCmd.BIND_POTENTIAL;
    }

    protected String defaultBindTable(int max) {
        StringBuilder bindTable = new StringBuilder();
        for(int i = 1; i <= max; i++) {
            bindTable.append(String.format("%02x", i)).append("0000000000");
        }
        return bindTable.toString();
    }

    protected Map<String, String> bindTableParser(String payload) {
        String[] bindTables = StrUtil.split(payload, 12);
        Map<String, String> outputCoilBindTable = new LinkedHashMap<>();
        for(String bindItem : bindTables) {
            outputCoilBindTable.put(
                    sub(bindItem, 0, 2, false, "00"),
                    sub(bindItem, 2, 12, true, "0000000000")
            );
        }
        return outputCoilBindTable;
    }
}
